package com.guchenbo.example.thread;

import com.guchenbo.example.lock.WaitClientCloseServer;

public class WaitDemo {
    public static void main(String[] args) {
        WaitDemo demo = new WaitDemo();
        //        demo.test1();
        //        demo.test2();
        //        demo.test3();
        //        demo.test12();
        //        demo.test22();
        //        demo.test32();
        demo.test4();
    }

    /**
     * t1获得锁不释放
     * t2获取锁阻塞
     * main中断t2，t2要获取锁之后才能响应中断
     */
    private void test4() {
        Wait lock = new Wait();
        Thread t1 = ThreadFactory.create("t1", () -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " lock and 不释放");
                new WaitClientCloseServer().start(10000);
                System.out.println(Thread.currentThread().getName() + " 释放");
            }
        });
        t1.start();
        Thread t2 = ThreadFactory.create("t2", () -> {
            synchronized (lock) {
                System.out.println(
                                Thread.currentThread().getName() + " lock " + Thread.currentThread().isInterrupted());
            }
        });
        t2.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("main 中断 t2");
        t2.interrupt();
    }

    /**
     * t1线程wait然后被intercept
     * t2线程占用锁
     * main线程中断t1
     */
    private void test32() {
        Wait lock = new Wait();
        Thread t1 = ThreadFactory.create("t1", () -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " lock and wait");
                    lock.wait();
                } catch (InterruptedException e) {
                    //                    throw new RuntimeException(e);
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        Thread t2 = ThreadFactory.create("t2", () -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " lock and 不释放");
                new WaitClientCloseServer().start(10000);
                System.out.println(Thread.currentThread().getName() + " 释放");
            }
        });
        t2.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("main 中断 t1");
        t1.interrupt();
    }

    /**
     * main线程wait超时
     * t1不释放锁
     */
    private void test22() {
        Wait lock = new Wait();
        synchronized (lock) {
            ThreadFactory.create("t1", () -> {
                synchronized (lock) {
                    try {
                        System.out.println(Thread.currentThread().getName() + " lock ");
                        Thread.sleep(3000);
                        System.out.println(Thread.currentThread().getName() + " notify 不释放锁");
                        new WaitClientCloseServer().start(10000);
                        System.out.println(Thread.currentThread().getName() + " 释放锁");
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
            try {
                System.out.println("wait");
                lock.wait(2000);
                System.out.println("继续执行");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * main线程wait
     * t1线程notify，但是不释放锁
     */
    private void test12() {
        Wait lock = new Wait();
        synchronized (lock) {
            ThreadFactory.create("t1", () -> {
                synchronized (lock) {
                    try {
                        System.out.println(Thread.currentThread().getName() + " lock ");
                        Thread.sleep(3000);
                        lock.notify();
                        System.out.println(Thread.currentThread().getName() + " notify and 不释放锁");
                        new WaitClientCloseServer().start(10000);
                        System.out.println(Thread.currentThread().getName() + " 释放锁");
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
            try {
                System.out.println("wait");
                lock.wait();
                System.out.println("继续执行");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * t1线程wait然后被intercept
     */
    private void test3() {
        Wait lock = new Wait();
        Thread t1 = ThreadFactory.create("t1", () -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " lock and wait");
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        t1.interrupt();

    }

    /**
     * main线程wait超时
     */
    private void test2() {
        Wait lock = new Wait();
        synchronized (lock) {
            try {
                System.out.println("wait");
                lock.wait(3000);
                System.out.println("继续执行");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * main线程wait
     * t1线程notify
     */
    private void test1() {
        Wait lock = new Wait();
        synchronized (lock) {
            ThreadFactory.create("t1", () -> {
                synchronized (lock) {
                    try {
                        System.out.println(Thread.currentThread().getName() + " lock ");
                        Thread.sleep(3000);
                        System.out.println(Thread.currentThread().getName() + " notify ");
                        lock.notify();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
            try {
                System.out.println("wait");
                lock.wait();
                System.out.println("继续执行");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    static class ThreadA extends Thread {

        public ThreadA(String name) {
            super(name);
        }

        public void run() {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "获取之后不释放");
                new WaitClientCloseServer().start(1000);
            }
        }
    }

    static class ThreadFactory {
        public static Thread create(String name, Runnable runnable) {
            Thread thread = new Thread(runnable);
            thread.setName(name);
            return thread;
        }
    }

}
